package com.jackstraw.jack_base.mq.common.entity;

import com.jackstraw.jack_base.mq.common.aspect.contextholder.MqContextHolder;
import com.jackstraw.jack_base.util.CollectionUtil;
import com.jackstraw.jack_base.util.ObjectUtil;
import com.jackstraw.jack_base.util.StringUtil;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

import java.util.HashMap;
import java.util.Map;

/**
 * MQ路由类
 *
 * @param <MTS>
 */
public abstract class MQRoutingTemplate<MTS extends MQTemplateS,
        MP extends MQProperties<E, P, C, MTS>,
        E extends MQEntity<P, C, MTS, E>,
        P extends MQProducer,
        C extends MQConsumer>
        implements InitializingBean {

    /**
     * 配置文件类
     */
    private MP defaultProperties;

    /**
     * 默认ServerName
     */
    private String defaultServerName;

    /**
     * 默认GroupName
     */
    private String defaultGroupName;

    /**
     * 默认TopicName
     */
    private String defaultTopicName;

    /**
     * 默认MQTemplateS
     */
    private MTS defaultMQTemplateS;

    /**
     * ServerName和MQTemplateS对应关系
     */
    private Map<String, MTS> targetMQTemplateSMap = new HashMap<>();

    private MP getDefaultProperties() {
        return defaultProperties;
    }

    public void setDefaultProperties(MP defaultProperties) {
        this.defaultProperties = defaultProperties;
    }

    private String getDefaultServerName() {
        return defaultServerName;
    }

    public void setDefaultServerName(String defaultServerName) {
        this.defaultServerName = defaultServerName;
    }

    private String getDefaultGroupName() {
        return defaultGroupName;
    }

    public void setDefaultGroupName(String defaultGroupName) {
        this.defaultGroupName = defaultGroupName;
    }

    private String getDefaultTopicName() {
        return defaultTopicName;
    }

    public void setDefaultTopicName(String defaultTopicName) {
        this.defaultTopicName = defaultTopicName;
    }

    private MTS getDefaultMQTemplateS() {
        return defaultMQTemplateS;
    }

    public void setDefaultMQTemplateS(MTS defaultMQTemplateS) {
        this.defaultMQTemplateS = defaultMQTemplateS;
    }

    private Map<String, MTS> getTargetMQTemplateSMap() {
        return targetMQTemplateSMap;
    }

    public void setTargetMQTemplateSMap(Map<String, MTS> targetMQTemplateSMap) {
        this.targetMQTemplateSMap = targetMQTemplateSMap;
    }

    /**
     * 配置文件类
     */
    private MP resolvedProperties;

    /**
     * 默认ServerName
     */
    private String resolvedServerName;

    /**
     * 默认GroupName
     */
    private String resolvedGroupName;

    /**
     * 默认TopicName
     */
    private String resolvedTopicName;

    /**
     * 默认MQTemplateS
     */
    private MTS resolvedMQTemplateS;

    /**
     * ServerName和MQTemplateS对应关系
     */
    private Map<String, MTS> resolvedMQTemplateSMap = new HashMap<>();

    public MP getResolvedProperties() {
        return resolvedProperties;
    }

    private void setResolvedProperties(MP resolvedProperties) {
        this.resolvedProperties = resolvedProperties;
    }

    public String getResolvedServerName() {
        return resolvedServerName;
    }

    private void setResolvedServerName(String resolvedServerName) {
        this.resolvedServerName = resolvedServerName;
    }

    public String getResolvedGroupName() {
        return resolvedGroupName;
    }

    private void setResolvedGroupName(String resolvedGroupName) {
        this.resolvedGroupName = resolvedGroupName;
    }

    public String getResolvedTopicName() {
        return resolvedTopicName;
    }

    private void setResolvedTopicName(String resolvedTopicName) {
        this.resolvedTopicName = resolvedTopicName;
    }

    public MTS getResolvedMQTemplateS() {
        return resolvedMQTemplateS;
    }

    public MTS getResolvedMQTemplateS(String serverName) {
        if (StringUtil.StringUtilsBylang3.isEmpty(serverName)) {
            return this.getResolvedMQTemplateS();
        }
        return this.getResolvedMQTemplateSMap().get(serverName);
    }

    private void setResolvedMQTemplateS(MTS resolvedMQTemplateS) {
        this.resolvedMQTemplateS = resolvedMQTemplateS;
    }

    public Map<String, MTS> getResolvedMQTemplateSMap() {
        return resolvedMQTemplateSMap;
    }

    private void setResolvedMQTemplateSMap(Map<String, MTS> resolvedMQTemplateSMap) {
        this.resolvedMQTemplateSMap = resolvedMQTemplateSMap;
    }


    private Boolean lenientFallback = false;


    private Boolean getLenientFallback() {
        return lenientFallback;
    }

    public void setLenientFallback(Boolean lenientFallback) {
        this.lenientFallback = lenientFallback;
    }

    @Nullable
    public String resolveSpecifiedLookupKey(String lookupKey) {
        return lookupKey;
    }

    @Nullable
    public Object resolveSpecifiedEntity(Object entity) {
        return entity;
    }

    @Nullable
    protected String determineCurrentLookupKey() {
        String serverName = MqContextHolder.getServerName();
        if (StringUtil.StringUtilsBylang3.isEmpty(serverName)) {
            serverName = this.getResolvedServerName();
        }
        return serverName;
    }

    @Nullable
    public MTS determineTargetEntity() {
        Assert.notNull(this.getResolvedMQTemplateSMap(), "Template router not initialized");
        String lookupKey = determineCurrentLookupKey();
        MTS mqTemplateS = this.getResolvedMQTemplateSMap().get(lookupKey);
        if (mqTemplateS == null && (this.getLenientFallback() || lookupKey == null)) {
            mqTemplateS = this.getResolvedMQTemplateS();
        }
        if (mqTemplateS == null) {
            throw new IllegalStateException("MQ Cannot determine target Template for lookup key [" + lookupKey + "]");
        }
        return mqTemplateS;
    }


    @Override
    public void afterPropertiesSet() throws Exception {

        if (this.getDefaultProperties() == null) {
            throw new IllegalArgumentException("MQ Property 'defaultProperties' is required");
        }

        this.setResolvedProperties(this.getDefaultProperties());

        if (StringUtil.StringUtilsBylang3.isEmpty(this.getDefaultServerName())) {
            throw new IllegalArgumentException("MQ Property 'defaultServerName' is required");
        }

        this.setResolvedServerName(this.getDefaultServerName());

        if (StringUtil.StringUtilsBylang3.isEmpty(this.getDefaultGroupName())) {
            throw new IllegalArgumentException("MQ Property 'defaultGroupName' is required");
        }

        this.setResolvedGroupName(this.getDefaultGroupName());

        // TODO 不一定是必须的，暂时注释掉
        //if (StringUtil.StringUtilsBylang3.isEmpty(this.getDefaultTopicName())) {
        //    throw new IllegalArgumentException("MQ Property 'defaultTopicName' is required");
        // }

        this.setResolvedTopicName(this.defaultTopicName);

        if (ObjectUtil.ObjectUtilByLang3.isEmpty(this.getDefaultMQTemplateS())) {
            throw new IllegalArgumentException("MQ Property 'defaultMQTemplateS' is required");
        }

        this.setResolvedMQTemplateS(this.getDefaultMQTemplateS());

        if (CollectionUtil.MapUtil.isEmpty(this.getTargetMQTemplateSMap())) {
            throw new IllegalArgumentException("MQ Property 'targetMQTemplateSMap' is required");
        }

        this.setResolvedMQTemplateSMap(this.getTargetMQTemplateSMap());

    }
}
